package com.atguigu.controller;

import com.atguigu.exception.MyException;
import com.atguigu.service.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;

import java.io.FileNotFoundException;

/**
 * @author ：HB
 * @date ：Created in 2020/10/30 19:12
 * @description：springmvc异常处理 为什么需要有SpringMVC异常：
 * 以前是在业务层try catch,实际工作中，抓到的异常会进行相应的处理操作，把哪些异常信息存储到数据库中，日志中。。
 * try catch的缺点：1. 业务代码和异常处理的逻辑混合在一起
 * 2. 如果多个地方抛出的是同样的异常，会造成业务代码的臃肿
 * 所以，使用java中的抽取思想，专门有一个类，来处理同样的异常，使用某个组件专门处理某种异常
 * <p>
 * 系统中异常包括两类：预期异常和运行时异常RuntimeException，前者通过捕获异常从而获取异常信息，
 * 后者主要通过规范代码开发、测试等手段减少运行时异常的发生。
 * 系统的Dao、Service、Controller出现都通过throws Exception向上抛出，
 * Controller层是springmvc框架调用的，所以最后由SpringMVC前端控制器交由异常处理器进行异常处理
 * <p>
 * 前端控制器会找一个异常处理器组件：HandlerExceptionResolver
 * springMvc本身已经为我们定义好了一些异常处理器
 * <p>
 * springmvc异常处理的两种方式：
 * 1. 使用SpringMvc提供的简单异常处理器SimpleMappingExceptionResolver
 * 2. 实现Spring的异常处理接口HandlerExceptionResolver自定义自己的异常处理器
 *
 * @ControllerAdvice：标注当前注解，在控制器中所有的异常处理的方法变成全局的，其他的控制器也能使用
 * 只要出现异常，就会交给这个类进行处理
 */
@ControllerAdvice
@Controller
public class ExceptionController {
    @Autowired
    private DemoService demoService;

    /**
     * 测试地址：http://localhost:8080/springmvc_exception/show
     *
     * @return
     * @throws FileNotFoundException
     * @throws MyException
     */
    @RequestMapping(value = "/show")
    public String show() throws FileNotFoundException, MyException {
        System.out.println("show running......");
        //抛出类型转换异常
        demoService.show1();
        //抛出除零异常
        //demoService.show2();
        //文件找不到异常
        //demoService.show3();
        //空指针异常
        //demoService.show4();
        //自定义异常
        //demoService.show5();
        return "index";
    }

    /**
     * 异常处理器注解：   @ExceptionHandler
     * 这个注解一旦标注在方法中之后，就具备了捕获异常的功能 相当于try catch 中的catch的功能
     * 把带有这个注解的方法设置在controller层中，这个controller的所有方法只要出现毛病
     * 有这个 @ExceptionHandler注解标注的方法就会去捕获异常信息
     *
     * @ExceptionHandler支持多个异常的方法，最精确的异常优先匹配。只为当前controller的方法捕获异常
     * @ExceptionHandler的作用主要在于声明一个或多个类型的异常，当符合条件的Controller抛出这些异常之后将会对这些异常进行捕获，
     * 然后按照其标注的方法的逻辑进行处理
     *
     * @ControllerAdvice:标注在类中，表示这个类中的捕获异常的方法可以捕获到其他controller层中的异常信息
     */
    @ExceptionHandler
    public String ThrowableHandler(Throwable e) {
        System.out.println("e = " + e.getMessage());
        return "error";
    }

    /**
     * 测试接口：http://localhost:8080/springmvc_exception/testExceptionHandler
     * 用来测试@ExceptionHandler处理异常
     * @return
     */
    @RequestMapping("/testExceptionHandler")
    public String testExceptionHandler() {
        System.out.println(1/0);
        return "success";
    }
}
